home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / OpenDoc A6 / OpenDoc Parts Framework / OPF / Found / FWString / Include / FWCharIt.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-21  |  15.2 KB  |  470 lines  |  [TEXT/MPS ]

  1. #ifndef FWCHARIT_H
  2. #define FWCHARIT_H
  3. //========================================================================================
  4. //
  5. //    File:                FWCharIt.h
  6. //    Release Version:    $ 1.0d1 $
  7. //
  8. //    Creation Date:        3/28/94
  9. //
  10. //    Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //========================================================================================
  13.  
  14. #ifndef FWEXCDEF_H
  15. #include "FWExcDef.h"
  16. #endif
  17.  
  18. #ifndef   FWMATH_H
  19. #include "FWMath.h"
  20. #endif
  21.  
  22. #ifndef FWPRIDEB_H
  23. #include "FWPriDeb.h"
  24. #endif
  25.  
  26. #ifndef FWCHARAC_H
  27. #include "FWCharac.h"
  28. #endif
  29.  
  30. #define FW_DEBUG_TEXT_ITERATORS
  31.  
  32.  
  33. //========================================================================================
  34. //                            Design Notes for Text Readers
  35. //
  36. //    Text readers are designed to be as fast and light-weight as possible.  We assume
  37. //    that in over 90% of the usage of Text readers, the reader will be used to make
  38. //    one sequential pass through the data structure, operating on one character at a time.
  39. //    The first design goal is therefore:
  40. //        1) Make GetCharacterAndAdvance be as efficient as possible.
  41. //    In order to achieve full efficiency, we need to minimize overhead for error checking
  42. //    for reading past the end of the data structure.  We therefore set this requirement:
  43. //        2) Rely on a clear contract to minimize overhead.  It is not necessary for
  44. //        iterators to fail gracefully when misused.
  45. //    As stated above, in 90% of the cases, the text is read in one forward pass.  However,
  46. //  reading backward through the text is a surprisingly large portion of the remaining
  47. //  10%, and if not supported, significantly reduces the usefulness of readers.  We
  48. //    therefore attempt to achieve this goal:
  49. //        3) Make "put back" a relatively efficient operation.  Make it possible to
  50. //        read backwards through the data structure.
  51. //    Often a client iterating over text will want to note the position of some character
  52. //    or token in the text.  We therefore set another goal:
  53. //        4) Support GetPosition ('tell') and SetPosition ('seek') operations.
  54. //    This last goal implies a specific need to handle the case where a client attempts to
  55. //    seek past the end of the text data structure.  In this case, to achieve efficiency,
  56. //    we invoke 2), by setting this requirement:
  57. //        5) It is acceptable to state in the contract that an attempt to SetPosition to
  58. //        an arbitrary position may fail.  However, a client can use GetLength to find
  59. //        the length of the data structure; it is safe to SetPosition to any value greater
  60. //        than or equal to zero, and less than the length of the data structure.
  61. //========================================================================================
  62.  
  63. //========================================================================================
  64. //    CLASS FW_CTextReader
  65. //
  66. //    A base class for iterators that read over a data structure containing characters.
  67. //
  68. //    It is possible to create a TextReader to read over any text data structure, as long
  69. //    as the following constraints are met:
  70. //
  71. //    1) It must be possible to get the total number of characters in the data structure
  72. //       at the time the text reader is constructed.
  73. //    1a) Of course, we assume that the length and content of the data structure does
  74. //        not change while the iterator is being used!
  75. //    2) The data members fStart, fLimit, and fNext are updated
  76. //
  77. //
  78. //    Invariant:
  79. //        ((fStart<=fNext) && (fNext<fLimit))
  80. //     || ((fStart-1==fNext) && (fBufferSum==0))
  81. //     || ((fNext==fLimit) && (fBufferSum==GetLength())
  82. //========================================================================================
  83.  
  84. class FW_CTextReader : public _FW_CAutoDestructObject
  85. {
  86.  
  87. public:
  88.  
  89.     // ----- General
  90.     
  91.     ~FW_CTextReader();
  92.     FW_CTextReader(const FW_Byte    *chunk1Start, // start of first contiguous chunk
  93.                    const FW_Byte     *chunk1Limit, // limit of first contiguous chunk
  94.                    FW_CharacterCount totalLength);// total characters in data structure
  95.     
  96.     FW_CharacterCount GetPosition();
  97.         // Get the current position, where 0 is first character in data structure.
  98.  
  99.     void SetPosition(FW_CharacterCount position);
  100.         // Set the position to position.
  101.         // The result is undefined if position is outside the bounds of the data structure.
  102.  
  103.     FW_CharacterCount GetLength();
  104.         // Get number of characters in data structure.
  105.     
  106.     // ----- Character-by-character iteration
  107.  
  108.     void Advance();
  109.         // Advance by one character.
  110.         
  111.     void Backup();
  112.         // Backup by one character.
  113.     
  114.     FW_Char PeekCharacter();
  115.         // Return the current character without advancing.  Can be used for lookahead.
  116.     
  117.     FW_Char GetCharacterAndAdvance();
  118.         // Get the current character and advance.
  119.     
  120.     FW_Char BackupAndGetCharacter();
  121.         // Backup and get previous character.
  122.     
  123.     // ----- Chunky iteration
  124.     //     With chunky iteration, client is responsible for translating between bytes and characters.
  125.     //    The static member functions FW_CharactersInBlock
  126.     //    and FW_CString::BytesInString may be used to do the translation.
  127.     
  128.     void Advance(FW_CharacterCount delta);
  129.         // Advance by delta characters.
  130.         
  131.     void Backup(FW_CharacterCount delta);
  132.         // Backup by delta characters.
  133.     
  134.     void PeekRunAhead(const FW_Byte*& start, FW_ByteCount& length);
  135.         // Peek ahead into current buffer of bytes
  136.         // Use Advance(delta) to inform iterator of number of characters consumed
  137.     
  138.     void PeekRunBehind(const FW_Byte*& end, FW_ByteCount& length);
  139.         // Peek behind into current buffer of bytes
  140.         // end points one past "current" byte!
  141.         // Use Backup(delta) to inform iterator of number of characters consumed
  142.  
  143. protected:
  144.  
  145.     void GetNextBuffer();
  146.         // Calls DoGetNextBuffer, and updates fNext, fBufferSum.
  147.     
  148.     void GetPreviousBuffer();
  149.         // Calls DoGetPreviousBuffer, and updates fNext, fBufferSum.
  150.  
  151.     virtual void DoGetNextBuffer() = 0;
  152.         // Get another buffer from text data structure.
  153.         // Updates fStart and fLimit.
  154.         // Must ensure that fStart<=fLimit.
  155.  
  156.     virtual void DoGetPreviousBuffer() = 0;
  157.         // Gets previous buffer from text data structure.
  158.         // Updates fStart and fLimit.
  159.         // Must ensure that fStart<=fLimit.
  160.  
  161.     const FW_Byte    *fStart;        // Start of current buffer
  162.     
  163.     const FW_Byte    *fLimit;        // One past last character of current buffer
  164.     
  165.     FW_CharacterCount    fLength;        // Total characters in data structure.
  166.  
  167. private:
  168.  
  169.     const FW_Byte    *fNext;            // Current position in buffer
  170.         
  171. #ifdef FW_DEBUG_TEXT_ITERATORS
  172.     void ClassInvariants();
  173. #else
  174.     void ClassInvariants() {}        // Let compiler optimize away the empty inline
  175. #endif
  176.  
  177.     FW_CharacterCount    fBufferSum;        // Total characters in previous buffers.
  178. };
  179.  
  180. //========================================================================================
  181. //    CLASS FW_CTextWriter
  182. //
  183. //    TextWriters are (intentionally) kept simpler than TextReaders.  We assume that there
  184. //    is no need to allow backing up in order to rewrite.  This results in a smaller and
  185. //    simpler interface.
  186. //========================================================================================
  187.  
  188. enum FW_TextWriterMode {FW_kTextWriteOver, FW_kTextAppend};
  189.  
  190. class FW_CTextWriter : public _FW_CAutoDestructObject
  191. {
  192. public:
  193.  
  194.     // ----- General
  195.     
  196.     virtual ~FW_CTextWriter();
  197.         // Flush the current buffer.
  198.         // Writer destructors must do whatever may be necessary to restore text structure
  199.         // to valid state, e.g. restore NUL termination, cached length member, etc.
  200.  
  201.     FW_CTextWriter(FW_Byte *chunk1Start, // start of first contiguous chunk
  202.                    FW_Byte *chunk1Limit);// limit of first contiguous chunk
  203.     
  204.     FW_CharacterCount GetPosition();
  205.         // Get the current position.
  206.  
  207.     // ----- Character-by-character iteration
  208.  
  209.     void PutCharacterAndAdvance(FW_Char character);
  210.         // Write the character into the data structure and advance to next position.
  211.  
  212.     // ----- Chunky iteration
  213.     
  214.     void WritePeek(FW_Byte*& start, FW_ByteCount& length);
  215.         // Returns start address and length of buffer to write into.
  216.     
  217.     void WritePeekAdvance(FW_Byte * const start, FW_ByteCount bytesWritten);
  218.         // Inform iterator of number of bytes written into peek buffer
  219.         // start value must be same as returned by WritePeek
  220.         // No calls to PutCharacterAndAdvance between WritePeek and WritePeekAdvance!
  221.  
  222. protected:
  223.  
  224.     virtual void DoFlushAndGetNextBuffer() = 0;
  225.         // Flush the current buffer.
  226.         // Get another buffer from text data structure, update fNext and fLimit.
  227.     
  228.     void FlushAndGetNextBuffer();
  229.         // Calls DoFlushAndGetNextBuffer and updates fBufferSum.
  230.  
  231.     FW_CharacterCount    fBufferSum;    // Total characters flushed in previous buffers.
  232.     FW_Byte    *fStart;        // First byte in this buffer
  233.     FW_Byte    *fLimit;        // One past last byte of current buffer
  234.     FW_Byte    *fNext;            // Current position in buffer
  235. };
  236.  
  237. //========================================================================================
  238. //    CLASS FW_CMemoryReader
  239. //
  240. //    A class for iterating over a buffer of characters.
  241. //========================================================================================
  242.  
  243. class FW_CMemoryReader : public FW_CTextReader
  244. {
  245. public:
  246.  
  247.     ~FW_CMemoryReader();
  248.     FW_CMemoryReader(const FW_Byte * buffer, FW_ByteCount bytes);
  249.     FW_CMemoryReader(const FW_Char * buffer, FW_CharacterCount characters);
  250.     
  251. protected:
  252.  
  253.     virtual void DoGetNextBuffer();
  254.     virtual void DoGetPreviousBuffer();
  255.  
  256. };
  257.  
  258. //========================================================================================
  259. //    CLASS FW_CMemoryWriter
  260. //
  261. //    A class for writing into a buffer of characters.
  262. //========================================================================================
  263.  
  264. class FW_CMemoryWriter : public FW_CTextWriter
  265. {
  266. public:
  267.  
  268.     ~FW_CMemoryWriter();
  269.     FW_CMemoryWriter(FW_Byte * buffer, FW_ByteCount capacity);
  270.  
  271. protected:
  272.  
  273.     virtual void DoFlushAndGetNextBuffer();
  274.  
  275. };
  276.  
  277. //========================================================================================
  278. //    CLASS FW_CTextReader
  279. //========================================================================================
  280.  
  281. //----------------------------------------------------------------------------------------
  282. //    FW_CTextReader::GetLength
  283. //----------------------------------------------------------------------------------------
  284.  
  285. inline FW_CharacterCount FW_CTextReader::GetLength()
  286. {
  287.     return fLength;
  288. }
  289.  
  290. //----------------------------------------------------------------------------------------
  291. //    FW_CTextReader::PeekRunAhead
  292. //----------------------------------------------------------------------------------------
  293.  
  294. inline void FW_CTextReader::PeekRunAhead(const FW_Byte*& start,
  295.                                                             FW_ByteCount& length)
  296. {
  297.     start = fNext;
  298.     length = fLimit-fNext;
  299. }
  300.  
  301. //----------------------------------------------------------------------------------------
  302. //    FW_CTextReader::PeekRunBehind
  303. //----------------------------------------------------------------------------------------
  304.  
  305. inline void FW_CTextReader::PeekRunBehind(const FW_Byte*& end,
  306.                                                             FW_ByteCount& length)
  307. {
  308.     end = fNext;
  309.     length = fNext-fStart;
  310. }
  311.  
  312. //----------------------------------------------------------------------------------------
  313. //    FW_CTextReader::Advance
  314. //----------------------------------------------------------------------------------------
  315.  
  316. inline void FW_CTextReader::Advance()
  317. {
  318.     ClassInvariants();
  319. #ifdef  FW_VARIABLE_WIDTH_CHARACTERS
  320.     fNext += BytesInString(fNext, 1);
  321. #else
  322.     fNext += sizeof(FW_Char);
  323. #endif
  324.     if (fNext == fLimit)
  325.         GetNextBuffer();
  326.     ClassInvariants();
  327. }
  328.  
  329. //----------------------------------------------------------------------------------------
  330. //    FW_CTextReader::Backup
  331. //----------------------------------------------------------------------------------------
  332.  
  333. inline void FW_CTextReader::Backup()
  334. {
  335.     ClassInvariants();
  336.     if (fNext == fStart)
  337.         GetPreviousBuffer();
  338. #ifdef  FW_VARIABLE_WIDTH_CHARACTERS
  339.     NotYetImplemented();
  340. #else
  341.     fNext -= sizeof(FW_Char);
  342. #endif
  343.     ClassInvariants();
  344. }
  345.  
  346. //----------------------------------------------------------------------------------------
  347. //    FW_CTextReader::PeekCharacter
  348. //----------------------------------------------------------------------------------------
  349.  
  350. inline FW_Char FW_CTextReader::PeekCharacter()
  351. {
  352.     ClassInvariants();
  353.     if (fNext>=fStart && fNext<fLimit)
  354.     {
  355. #ifdef  FW_VARIABLE_WIDTH_CHARACTERS
  356.         return NotYetImplemented();
  357. #else
  358.         return *((FW_Char*)fNext);
  359. #endif
  360.     }
  361.     else
  362.         return FW_kNulCharacter;
  363. }
  364.  
  365. //----------------------------------------------------------------------------------------
  366. //    FW_CTextReader::GetCharacterAndAdvance
  367. //----------------------------------------------------------------------------------------
  368.  
  369. inline FW_Char FW_CTextReader::GetCharacterAndAdvance()
  370. {
  371.     ClassInvariants();
  372.     register FW_Char temp = PeekCharacter();
  373.     if (temp!=FW_kNulCharacter)
  374.         Advance();
  375.     ClassInvariants();
  376.     return temp;
  377. }
  378.  
  379. //----------------------------------------------------------------------------------------
  380. //    FW_CTextReader::BackupAndGetCharacter
  381. //----------------------------------------------------------------------------------------
  382.  
  383. inline FW_Char FW_CTextReader::BackupAndGetCharacter()
  384. {
  385.     ClassInvariants();
  386.     Backup();
  387.     ClassInvariants();
  388.     return PeekCharacter();
  389. }
  390.  
  391. //----------------------------------------------------------------------------------------
  392. //    FW_CTextReader::GetPosition
  393. //----------------------------------------------------------------------------------------
  394.  
  395. inline FW_CharacterCount FW_CTextReader::GetPosition()
  396. {
  397.     ClassInvariants();
  398.     if (fNext == fLimit)
  399.         return fBufferSum;
  400.     else
  401.         return fBufferSum + FW_CharactersInBlock(fStart, fNext - fStart);
  402. }
  403.  
  404. //========================================================================================
  405. //    CLASS FW_CTextWriter
  406. //========================================================================================
  407.  
  408. //----------------------------------------------------------------------------------------
  409. //    FW_CTextWriter::PutCharacterAndAdvance
  410. //----------------------------------------------------------------------------------------
  411.  
  412. inline void FW_CTextWriter::PutCharacterAndAdvance(FW_Char character)
  413. {
  414.     if (fNext >= fLimit)
  415.         FlushAndGetNextBuffer();
  416. #ifdef  FW_VARIABLE_WIDTH_CHARACTERS
  417.     NotYetImplemented();
  418. #else
  419.     *((FW_Char*)fNext) = character;
  420.     fNext += sizeof(FW_Char);
  421. #endif
  422. }
  423.  
  424. //----------------------------------------------------------------------------------------
  425. //    FW_CTextWriter::GetPosition
  426. //----------------------------------------------------------------------------------------
  427.  
  428. inline FW_CharacterCount FW_CTextWriter::GetPosition()
  429. {
  430.     return fBufferSum + FW_CharactersInBlock(fStart, fStart-fNext);
  431. }
  432.  
  433. //----------------------------------------------------------------------------------------
  434. //    FW_CTextWriter::FlushAndGetNextBuffer
  435. //----------------------------------------------------------------------------------------
  436.  
  437. inline void FW_CTextWriter::FlushAndGetNextBuffer()
  438. {
  439.     fBufferSum += FW_CharactersInBlock(fStart, fStart-fNext);
  440.     DoFlushAndGetNextBuffer();
  441. }
  442.  
  443. //----------------------------------------------------------------------------------------
  444. //    FW_CTextWriter::WritePeek
  445. //----------------------------------------------------------------------------------------
  446.  
  447. inline void FW_CTextWriter::WritePeek(FW_Byte*& start, 
  448.                                                  FW_ByteCount& length)
  449. {
  450.     if (fNext >= fLimit)
  451.         FlushAndGetNextBuffer();
  452.     start = fNext;
  453.     length = fLimit-fNext;
  454. }
  455.  
  456. //----------------------------------------------------------------------------------------
  457. //    FW_CTextWriter::WritePeekAdvance
  458. //----------------------------------------------------------------------------------------
  459.  
  460. inline void FW_CTextWriter::WritePeekAdvance(FW_Byte * const start, 
  461.                                                         FW_ByteCount bytesWritten)
  462. {
  463.     FW_ASSERT(start == fNext);
  464.     FW_ASSERT(bytesWritten <= fLimit-fNext);
  465.     fNext += bytesWritten;
  466. }
  467.  
  468.  
  469. #endif
  470.